package pe.bf.extranet.dao.impl;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import oracle.jdbc.OracleTypes;
import org.apache.log4j.Logger;
import pe.bf.base.dao.impl.BaseDAOImpl;
import pe.bf.base.types.OutParameter;
import pe.bf.domain.bean.Contacto;
import pe.bf.domain.bean.Departamento;
import pe.bf.domain.bean.Distrito;
import pe.bf.domain.bean.Empresa;
import pe.bf.domain.bean.Provincia;
import pe.bf.domain.exceptions.DomainException;
import pe.bf.extranet.dao.EmpresaDAO;

public class EmpresaDAOImpl extends BaseDAOImpl implements EmpresaDAO {

	
	Logger logger = Logger.getLogger(EmpresaDAOImpl.class);
	
	 static final String USP_CRE_EMPRESA = "{call PKG_EMPRESA.USP_CRE_EMPRESA(?,?,?,?,?,?,?,?,?,?)}";
	 static final String USP_ACT_EMPRESA = "{call PKG_EMPRESA.USP_ACT_EMPRESA(?,?,?,?,?,?,?,?,?)}";
	 static final String USP_BAJA_EMPRESA = "{call PKG_EMPRESA.USP_BAJA_EMPRESA(?)}";
	 static final String USP_CREA_CONTACTO = "{call PKG_EMPRESA.USP_REGISTRA_CONTACTOS(?,?,?,?,?)}";
	 static final String USP_ELIMINA_CONTACTO = "{call PKG_EMPRESA.USP_ELIMINA_CONTACTO(?)}";
	 static final String USP_LISTAR_EMPRESAS = "{call PKG_EMPRESA.USP_LISTAR_EMPRESAS(?)}";
	 static final String USP_LISTAR_CONTACTOS = "{call PKG_EMPRESA.USP_LISTAR_CONTACTOS(?,?)}";
	 static final String USP_OBTENER_DISTRITO = "{call PKG_EMPRESA.USP_OBTENER_DISTRITO(?,?)}";
	 static final String USP_OBTENER_PROVINCIA = "{call PKG_EMPRESA.USP_OBTENER_PROVINCIA(?,?)}";
	 static final String USP_OBTENER_DEPARTAMENTO = "{call PKG_EMPRESA.USP_OBTENER_DEPARTAMENTO(?,?)}";
	 
	  
	public EmpresaDAOImpl(DataSource dataSource) {
		super(dataSource);
		// TODO Auto-generated constructor stub
	}

	@Override
	public Empresa crearEmpresa(Empresa empresa) throws DomainException {
		empresa.setIdEmpresa(invokeStoreProcedureGetId(USP_CRE_EMPRESA,   
				empresa.getRuc(),
				empresa.getNombres(),
				empresa.getRubro(),
				empresa.getDistrito(),
				empresa.getDireccion(),
				empresa.getTelefono1(),
				empresa.getTelefono2(),
				empresa.getHorario(),
				empresa.getDia_validar(),
				new OutParameter(OracleTypes.NUMBER)));
		limpiarContactos(empresa.getIdEmpresa());
		if(empresa.getContactos()!=null){
		for(Contacto contacto:empresa.getContactos()){
			registrarContacto(empresa.getIdEmpresa(),contacto);	
		}   
		}
			return empresa;
	}


	@Override
	public void limpiarContactos(long idEmpresa) throws DomainException {
		try {
			invokeStoreProcedure(USP_ELIMINA_CONTACTO, 
					idEmpresa
					);
		} catch (DomainException e) {
			throw new DomainException(e);
		}
	}
	
	
	@Override
	public void registrarContacto(long idEmpresa,Contacto contacto) throws DomainException {
		try {
			invokeStoreProcedure(USP_CREA_CONTACTO, 
					idEmpresa, 
					contacto.getNombres()  ,
					contacto.getCargo(),
					contacto.getTelefono(),
					contacto.getEmail()
					);
		} catch (DomainException e) {
			throw new DomainException(e);
		}
	}
	
	
	
	@Override
	public void crearEmpresaBatch(List<Empresa> empresaList)
			throws DomainException {

		for(Empresa empresa:empresaList){
			crearEmpresa(empresa);
		}

	}

	
	
	@Override
	public Empresa bajaEmpresa(Empresa empresa) throws DomainException {
		invokeStoreProcedure(USP_BAJA_EMPRESA,   
				empresa.getIdEmpresa());
		 
			return empresa;
	}
	
	
	@Override
	public Empresa actualizarEmpresa(Empresa empresa) throws DomainException {
		empresa.setIdEmpresa(invokeStoreProcedureGetId(USP_ACT_EMPRESA,   
				empresa.getIdEmpresa(),
				empresa.getRuc(),
				empresa.getNombres(),
				empresa.getRubro(),
				empresa.getDistrito(),
				empresa.getDireccion(),
				empresa.getTelefono1(),
				empresa.getTelefono2(),
				empresa.getHorario()));
		limpiarContactos(empresa.getIdEmpresa());
		for(Contacto contacto:empresa.getContactos()){
			registrarContacto(empresa.getIdEmpresa(),contacto);	
		}
		
		
			return empresa;
	}

	@Override
	public List<Empresa> listarEmpresas() throws DomainException {

		CallableStatement cal =invokeStoreProcedureCallable(USP_LISTAR_EMPRESAS, new OutParameter(OracleTypes.CURSOR));
		ResultSet resultSet=null;
		List<Empresa> empresaList = null;
		try {
			empresaList = new ArrayList<Empresa>();
			resultSet = (ResultSet) cal.getObject(1);
			while (resultSet.next()) {
				Empresa empresa = new Empresa();
				empresa.setIdEmpresa(resultSet.getLong("id_empresa"));
				empresa.setDireccion(resultSet.getString("direccion"));
				empresa.setRuc(resultSet.getString("ruc"));
				empresa.setEstado(resultSet.getString("estado"));
				empresa.setHorario(resultSet.getString("horario"));
				empresa.setNombres(resultSet.getString("nombres"));
				empresa.setTelefono1(resultSet.getString("telefono1"));
				empresa.setTelefono2(resultSet.getString("telefono2"));
				empresa.setRubro(resultSet.getString("rubro"));
				empresa.setDia_validar(resultSet.getString("dia_validar"));
				empresa.setDistrito(buscarDistrito(resultSet.getLong("id_distrito"))); 
				empresaList.add(empresa);
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally{
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return empresaList;
	}
	
	private Provincia buscarProvincia(long long1) throws DomainException {
		Provincia provincia = null;
		CallableStatement cal =invokeStoreProcedureCallable(USP_OBTENER_PROVINCIA, long1,new OutParameter(OracleTypes.CURSOR));//porque se puso una constante aqui?
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);
			while (resultSet.next()) {
				provincia = new Provincia();
				provincia.setIdProvincia(resultSet.getLong("id_provincia"));
				 provincia.setDescripcion(resultSet.getString("descripcion"));  
				 provincia.setDepartamento(buscarDepartamento(resultSet.getLong("id_departamento"))); 
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally{
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} 
		return provincia;
	}
	
	private Departamento buscarDepartamento(long long1) throws DomainException {
		Departamento departamento = null;
		CallableStatement cal =invokeStoreProcedureCallable(USP_OBTENER_DEPARTAMENTO, long1,new OutParameter(OracleTypes.CURSOR));//porque se puso una constante aqui?
		ResultSet resultSet = null;
		try {
			resultSet = (ResultSet) cal.getObject(2);
 
			while (resultSet.next()) {
				departamento = new Departamento();
				departamento.setIdDepartamento(resultSet.getLong("id_departamento"));
				departamento.setDescripcion(resultSet.getString("descripcion"));   
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally{
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return departamento;
	}
	
	private Distrito buscarDistrito(long long1) throws DomainException {
		Distrito distrito = null;
		CallableStatement cal =invokeStoreProcedureCallable(USP_OBTENER_DISTRITO, long1,new OutParameter(OracleTypes.CURSOR));//porque se puso una constante aqui?
		ResultSet resultSet=null;
		try {
			
			resultSet = (ResultSet) cal.getObject(2);
 
			while (resultSet.next()) {
				  distrito = new Distrito();
				  distrito.setIdDistrito(resultSet.getLong("id_distrito"));
				  distrito.setDescripcion(resultSet.getString("descripcion"));  
				  distrito.setProvincia(buscarProvincia(resultSet.getLong("id_provincia"))); 
			}
		} catch (SQLException e) {
			throw new DomainException(e);
		} finally{
			try {
				cal.getConnection().close();
				cal.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return distrito;
	}
	
	
	public List<Empresa> listarContactosEmpresas(List<Empresa> empresas)
			throws DomainException {
		List<Empresa> lista = empresas;
		List<Contacto> contactoList = null;

		try { 
			for(Empresa empresa:lista){
				CallableStatement cal =invokeStoreProcedureCallable(USP_LISTAR_CONTACTOS, empresa.getIdEmpresa(),new OutParameter(OracleTypes.CURSOR));
				ResultSet resultSet=null;
				resultSet = (ResultSet) cal.getObject(2);
				contactoList = new ArrayList<Contacto>();
				while (resultSet.next()) {
					Contacto contacto = new Contacto();
					contacto.setIdContacto(resultSet.getLong("id_contacto"));
					contacto.setNombres(resultSet.getString("nombres"));
					contacto.setCargo(resultSet.getString("cargo"));
					contacto.setTelefono(resultSet.getString("telefono"));
					contacto.setEmail(resultSet.getString("email"));
					contactoList.add(contacto);
				} 
				
				try {
					cal.getConnection().close();
					cal.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				
				empresa.setContactos(contactoList);
			} 
		} catch (SQLException e) {
			throw new DomainException(e);
		} 
		return lista;
	}
	

	@Override
	public void actualizarEmpresaBatch(List<Empresa> empresaList)
			throws DomainException {

	}

}
